/*
 * @Author: czy
 * @Date: 2021-04-24 08:14:52
 * @LastEditTime: 2021-05-21 22:24:09
 */
#include "const.h"
#include "datetime.h"

#include "sys/tick.h"

static hook hooks[MAX_HOOK_SIZE];
static int hook_length = 0;
static time_t TICK_TIMES = 0;

/**
 * @description: Determine if the hook queue is full.
 * @return TRUE if full, else FALSE.
 */
static int isFull(void)
{
    if (hook_length < MAX_HOOK_SIZE)
    {
        return FALSE;
    }
    return TRUE;
}

/**
 * @description: Submit hook function.
 * @param h Hook.
 */
void submit(hook h)
{
    if (!isFull())
    {
        hooks[hook_length] = h;
        hook_length++;
    }
}

/**
 * @description: Finish task.
 * @param index Task number.
 */
static void finish(int index)
{
    for (int i = hook_length - 1; i > index; i--)
    {
        hooks[i - 1] = hooks[i];
    }
    hook_length--;
}

/**
 * @description: Update tasks.
 * @param h     Hook.
 * @param index Task number.
 */
static void update(hook *h, int index)
{
    if (h->times == 0)
    {
        finish(index);
        return;
    }
    h->counter += 1000 / FREQUENCY;
    if (h->counter >= h->cycle)
    {
        h->func();
        if (h->times > 0)
        {
            h->times--;
            h->counter = 0;
        }
    }
}

/**
 * @description: Periodic clock interrupt.
 */
void tick(void)
{
    TICK_TIMES++;
    for (int i = 0; i < hook_length; i++)
    {
        update(&hooks[i], i);
    }
    return;
}

/**
 * @description: Get tick count.
 * @return Tick count.
 */
time_t gettick(void)
{
    return TICK_TIMES;
}